package com.base.core.network.http.support;

import com.base.core.lang.StringUtils;
import com.base.core.constant.HttpConstants;
import com.base.core.exception.SimpleHttpException;
import com.base.core.network.http.Http;
import com.base.core.network.http.HttpHeader;
import com.base.core.network.http.ResponseEntity;
import com.base.core.utils.MapUtils;
import okhttp3.*;

import java.io.IOException;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * OkHttp3 实现http
 * </p>
 *
 * @author becker
 * @date Created in 2019/12/24 19:06
 */
public class HttpOkHttp3 implements Http {

    private final OkHttpClient httpClient;


    public HttpOkHttp3() {
        this(new OkHttpClient().newBuilder()
                .connectTimeout(HttpConstants.TIMEOUT, TimeUnit.MILLISECONDS)
                .writeTimeout(HttpConstants.TIMEOUT, TimeUnit.MILLISECONDS)
                .readTimeout(HttpConstants.TIMEOUT,TimeUnit.MILLISECONDS)
                .build()
        );
    }

    public HttpOkHttp3(OkHttpClient httpClient) {
        this.httpClient = httpClient;
    }

    private ResponseEntity exec(Request.Builder requestBuilder) {
        this.addHeader(requestBuilder);
        Request request = requestBuilder.build();
        try (Response response = httpClient.newCall(request).execute()) {
            if (!response.isSuccessful()) {
                throw new SimpleHttpException("Unexpected code " + response);
            }
            ResponseEntity responseEntity = new ResponseEntity();
            responseEntity.setCode(response.code());
            responseEntity.setMessage(response.message());
            responseEntity.setBody(response.body().string());
            return responseEntity;
        } catch (IOException e) {
            throw new SimpleHttpException(e);
        }
    }

    /**
     * 添加request header
     *
     * @param builder Request.Builder
     */
    private void addHeader(Request.Builder builder) {
        builder.header(HttpConstants.USER_AGENT, HttpConstants.USER_AGENT_DATA);
    }

    /**
     * GET 请求
     *
     * @param url URL
     *
     * @return 结果
     */
    @Override
    public ResponseEntity get(String url) {
        return this.get(url, null, false);
    }

    /**
     * GET 请求
     *
     * @param url    URL
     * @param params 参数
     * @param encode 是否需要 url encode
     *
     * @return 结果
     */
    @Override
    public ResponseEntity get(String url, Map<String, String> params, boolean encode) {
        return this.get(url, params, null, encode);
    }

    /**
     * GET 请求
     *
     * @param url    URL
     * @param params 参数
     * @param header 请求头
     * @param encode 是否需要 url encode
     *
     * @return 结果
     */
    @Override
    public ResponseEntity get(String url, Map<String, String> params, HttpHeader header, boolean encode) {
        HttpUrl.Builder urlBuilder = HttpUrl.parse(url).newBuilder();
        if (encode) {
            MapUtils.forEach(params, urlBuilder::addEncodedQueryParameter);
        } else {
            MapUtils.forEach(params, urlBuilder::addQueryParameter);
        }
        HttpUrl httpUrl = urlBuilder.build();

        Request.Builder requestBuilder = new Request.Builder().url(httpUrl);
        if (header != null) {
            MapUtils.forEach(header.getHeaders(), requestBuilder::addHeader);
        }
        requestBuilder = requestBuilder.get();

        return exec(requestBuilder);
    }

    /**
     * POST 请求
     *
     * @param url URL
     *
     * @return 结果
     */
    @Override
    public ResponseEntity post(String url) {
        return this.post(url, HttpConstants.EMPTY);
    }

    /**
     * POST 请求
     *
     * @param url  URL
     * @param data JSON 参数
     *
     * @return 结果
     */
    @Override
    public ResponseEntity post(String url, String data) {
        return this.post(url, data, null);
    }

    /**
     * POST 请求
     *
     * @param url    URL
     * @param data   JSON 参数
     * @param header 请求头
     *
     * @return 结果
     */
    @Override
    public ResponseEntity post(String url, String data, HttpHeader header) {
        if (StringUtils.isEmpty(data)) {
            data = HttpConstants.EMPTY;
        }//"application/json;charset=utf-8"
        MediaType mediaType=MediaType.Companion.parse(HttpConstants.CONTENT_TYPE_JSON);
        RequestBody body=RequestBody.Companion.create("body参数",mediaType);

        Request.Builder requestBuilder = new Request.Builder().url(url);
        if (header != null) {
            MapUtils.forEach(header.getHeaders(), requestBuilder::addHeader);
        }
        requestBuilder = requestBuilder.post(body);

        return exec(requestBuilder);
    }

    /**
     * POST 请求
     *
     * @param url    URL
     * @param params form 参数
     * @param encode 是否需要 url encode
     *
     * @return 结果
     */
    @Override
    public ResponseEntity post(String url, Map<String, String> params, boolean encode) {
        return this.post(url, params, null, encode);
    }

    /**
     * POST 请求
     *
     * @param url    URL
     * @param params form 参数
     * @param header 请求头
     * @param encode 是否需要 url encode
     *
     * @return 结果
     */
    @Override
    public ResponseEntity post(String url, Map<String, String> params, HttpHeader header, boolean encode) {
        FormBody.Builder formBuilder = new FormBody.Builder();
        if (encode) {
            MapUtils.forEach(params, formBuilder::addEncoded);
        } else {
            MapUtils.forEach(params, formBuilder::add);
        }
        FormBody body = formBuilder.build();

        Request.Builder requestBuilder = new Request.Builder().url(url);
        if (header != null) {
            MapUtils.forEach(header.getHeaders(), requestBuilder::addHeader);
        }
        requestBuilder = requestBuilder.post(body);

        return exec(requestBuilder);
    }
}
